//package com.easylinkin.linkappapi.meterbilling.service.impl;
//
//import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
//import com.baomidou.mybatisplus.core.metadata.IPage;
//import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
//import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
//import com.easylinkin.bases.redis.util.RedisUtil;
//import com.easylinkin.linkappapi.common.utils.DateUtil;
//import com.easylinkin.linkappapi.meterbilling.entity.*;
//import com.easylinkin.linkappapi.meterbilling.entity.ext.GlobalRoomInfo;
//import com.easylinkin.linkappapi.meterbilling.mapper.*;
//import com.easylinkin.linkappapi.meterbilling.service.*;
//import com.easylinkin.linkappapi.meterbilling.util.MeterServiceControl;
//import lombok.extern.slf4j.Slf4j;
//import org.apache.commons.lang3.ObjectUtils;
//import org.quartz.Job;
//import org.quartz.JobExecutionContext;
//import org.quartz.JobExecutionException;
//import org.redisson.api.RLock;
//import org.redisson.api.RedissonClient;
//import org.springframework.context.annotation.Lazy;
//import org.springframework.stereotype.Service;
//import org.springframework.transaction.annotation.Transactional;
//
//import javax.annotation.Resource;
//import java.math.BigDecimal;
//import java.util.ArrayList;
//import java.util.Date;
//import java.util.List;
//import java.util.Map;
//import java.util.stream.Collectors;
//
///**
// * class info :房间支出消费任务 备份代码
// *
// * @author liuqihang
// * @date 2021/7/15 14:35
// */
//@Service
//@Slf4j
//@Transactional(rollbackFor = Exception.class)
//public class RoomExpensesBackupsServiceImpl extends ServiceImpl<RoomExpensesMapper, RoomExpensesBill> implements RoomExpensesService, Job {
//
//    @Resource
//    private ExpensesTimerTaskMapper expensesTimerTaskMapper;
//
//    @Resource
//    private BaseMeterBillingMapper baseMeterBillingMapper;
//
//    @Resource
//    private BillingStandardService billingStandardService;
//
//    @Resource
//    private EnergyConsumptionService energyConsumptionService;
//
//    @Resource
//    private RoomManagerService roomManagerService;
//
//    @Resource
//    private RoomInfoMapper roomInfoMapper;
//
//    @Resource
//    private MeterDeviceConfigMapper meterDeviceConfigMapper;
//
//    @Resource
//    private MeterRemedyMapper meterRemedyMapper;
//
//    @Resource@Lazy
//    private MeterRemedyService meterRemedyService;
//
//    @Resource
//    private RedissonClient redisson;
//
//    @Resource
//    private RedisUtil redisUtil;
//    @Resource
//    private MeterServiceControl meterServiceControl;
//
//    @Override
//    public void meterTimerTask() {
//        String lockKey = DateUtil.format(new Date(), DateUtil.YYYYMMDDHH_STRING);
//
//        //待验证锁机制
//        RLock redissonLock = redisson.getLock("room_expenses_" + lockKey);
//
//        if (redissonLock.tryLock()) {
//            try {
//                String usedKey = lockKey + "_room_timer";
//                if (redisUtil.hasKey(usedKey)) {
//                    return;
//                }
//                redisUtil.set(usedKey, true, 60);
//                //获取房间绑定设备
//
//                //获取补录的设备单独计算
//                List<MeterRemedy> meterRemedyList = getRemedyDeviceList(null, true);
//                QueryWrapper qw = new QueryWrapper();
//                qw.eq("delete_status","0");
//
//                //存在补录设备需要排除，进入单个设备请求扣费逻辑
//                if(!ObjectUtils.isEmpty(meterRemedyList)){
//                    log.info("补录的设备数量 size =" + meterRemedyList.size() + ", 进入单个设备请求");
//                    List<String> deviceCodes = meterRemedyList.stream().map(i->i.getDeviceCode()).collect(Collectors.toList());
//                    singleDeviceHandler(deviceCodes);
//                    qw.notIn("device_code", deviceCodes);
//                }
//                List<MeterDeviceConfig> list = meterDeviceConfigMapper.selectList(qw);
//                if(list == null || list.isEmpty()){
//                    log.info("无仪表设备记录（正常设备）");
//                    return ;
//                }
//
//                Date[] currentSettlementTimePeriod = getCurrentSettlementTimePeriod();
//
//                Map<String, List<RoomExpensesBill>> newestRoomExpensesBillRecordByDeviceCode = getNewestRoomExpensesBillRecordByDeviceCode(list);
//                List<EnergyConsumption> energyConsumptionDateList = null;
//                //获取ES数据
//                if(newestRoomExpensesBillRecordByDeviceCode == null){
//                    Date[] settlementTimePeriod = new Date[2];
//                    settlementTimePeriod[0] = null;
//                    settlementTimePeriod[1] = currentSettlementTimePeriod[1];
//                    energyConsumptionDateList = getEnergyConsumptionDateList(settlementTimePeriod, list);
//                }else {
//                    energyConsumptionDateList = calculationLastAndCurrntEnergyConsumptionDateList(currentSettlementTimePeriod, list, newestRoomExpensesBillRecordByDeviceCode);
//                }
//
//                if(energyConsumptionDateList == null || energyConsumptionDateList.isEmpty()){
//                    log.info("无设备流水记录");
//                    return ;
//                }
//                handlerData(energyConsumptionDateList, currentSettlementTimePeriod);
//
//                //保存定时任务运行时间段
//                ExpensesTimerTask expensesTimerTask = new ExpensesTimerTask();
//                saveSettlementTimePeriod(expensesTimerTask, currentSettlementTimePeriod);
//            } catch (Exception ex) {
//                log.error("RoomExpensesServiceImpl房间消费扣款任务异常 error info=:", ex);
//            } finally {
//                //如果不加isHeldByCurrentThread判断条件的话，偶发异常：attempt to unlock lock, not locked by current thread by node id
//                //lock.isLocked()：判断要解锁的key是否已被锁定。
//                //lock.isHeldByCurrentThread()：判断要解锁的key是否被当前线程持有。
//                if(redissonLock.isLocked() && redissonLock.isHeldByCurrentThread()){
//                    redissonLock.unlock();
//                }
//            }
//        }else {
//            log.info("获取锁'room_expenses_" + lockKey + "'失败");
//        }
//    }
//
//    /**
//     *  1：使用锁，保证同一时段类的计算不会执行两次（待验证）...添加redis的key过期时间，以及校验能耗记录起始时间;
//     *  2：异常设备读表数需要单独记录统计时间，全局统计时间需要添加标识（0：全部成功，1：有异常数据），需要新增异常设备的统计信息表
//     */
//    @Override
//    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
//        log.info("start execute room expenses task ................ start");
//        meterTimerTask();
//        log.info("start execute room expenses task ................ end");
//    }
//
//    public void singleDeviceHandler(List<String> deviceCodeList){
//        for (String deviceCode:
//                deviceCodeList) {
//            QueryWrapper qw = new QueryWrapper();
//            qw.eq("delete_status","0");
//            qw.eq("device_code", deviceCode);
//            List<MeterDeviceConfig> meterDeviceConfigList = meterDeviceConfigMapper.selectList(qw);
//            if(ObjectUtils.isEmpty(meterDeviceConfigList)){  continue; }
//
//            List<MeterRemedy> meterRemedyList = getRemedyDeviceList(deviceCode, false);
//            if(ObjectUtils.isEmpty(meterRemedyList)){
//                continue;
//            }
//            MeterRemedy meterRemedy = meterRemedyList.get(0);
//
//            Date[] settlementDate = getCurrentSettlementTimePeriod();
//
//            //获取设备数据
//            List<EnergyConsumption> energyConsumptionDateList = getEnergyConsumptionDateList(settlementDate, meterDeviceConfigList);
//
//            if(ObjectUtils.isEmpty(energyConsumptionDateList)){
//                continue;
//            }else {
//                EnergyConsumption ec = energyConsumptionDateList.get(0);
//                if(ObjectUtils.isEmpty(ec.getEndRead())){
//                    continue;
//                }
//                ec.setStartRead(meterRemedy.getEnergyAmount());
//                //被减数为补录的止码
//                ec.setAmount(ec.getEndRead().subtract(meterRemedy.getEnergyAmount()));
//                settlementDate[0] = meterRemedy.getCreateTime();
//                settlementDate[1] = new Date();
//                calculation(ec, settlementDate, null, 0);
//
//                //修改补录设备为已计算状态
//                meterRemedyService.restoreDeviceCalculateStatus(deviceCode, null);
//            }
//        }
//    }
//
//    /**
//     * 获取最新时段仪表读数 减去 上次时段仪表读数 得到实际仪表能耗
//     * @param currentSettlementTimePeriod
//     * @param list
//     * @return
//     */
//    public List<EnergyConsumption> calculationLastAndCurrntEnergyConsumptionDateList(Date[] currentSettlementTimePeriod, List<MeterDeviceConfig> list, Map<String, List<RoomExpensesBill>> newestRoomExpensesBillRecordByDeviceCode){
//        Map<String, List<MeterDeviceConfig>> meterDeviceMap = list.stream().collect(Collectors.groupingBy(MeterDeviceConfig::getDeviceCode));
//        List<EnergyConsumption> resultEnergyConsumptionDateList = new ArrayList<>();
//
//        List<EnergyConsumption> newEnergyConsumptionDateList = getEnergyConsumptionDateList(currentSettlementTimePeriod, list);
//        if(ObjectUtils.isEmpty(newEnergyConsumptionDateList)){
//            return null;
//        }
//        for (EnergyConsumption data:
//             newEnergyConsumptionDateList) {
//            String deviceCode = data.getDeviceCode();
//            if(data.getEndRead() == null){
//                continue;
//            }
//            if(ObjectUtils.isEmpty(newestRoomExpensesBillRecordByDeviceCode.get(deviceCode))){
//                //重新获取从0开始的设备流水
//                List<MeterDeviceConfig> meterDeviceConfigList = meterDeviceMap.get(deviceCode);
//                Date[] childTimePeriod = new Date[2];
//                childTimePeriod[0] = null;
//                childTimePeriod[1] = currentSettlementTimePeriod[1];
//                List<EnergyConsumption> childEnergyConsumptionDateList = getEnergyConsumptionDateList(childTimePeriod, meterDeviceConfigList);
//                if(ObjectUtils.isEmpty(childEnergyConsumptionDateList)){
//                    continue;
//                }
//                EnergyConsumption energyConsumption = childEnergyConsumptionDateList.get(0);
//                if(energyConsumption.getEndRead() == null){
//                    continue;
//                }
//                data.setStartRead(energyConsumption.getStartRead());
//                data.setEndRead(energyConsumption.getEndRead());
//                data.setAmount(energyConsumption.getAmount());
//            }else {
//                List<RoomExpensesBill> roomExpensesBillList = newestRoomExpensesBillRecordByDeviceCode.get(deviceCode);
//                RoomExpensesBill roomExpensesBill = roomExpensesBillList.get(0);
//                if(roomExpensesBill.getEndReadAmount() == null){
//                    continue;
//                }
//                data.setStartRead(roomExpensesBill.getEndReadAmount());
//                data.setAmount(data.getEndRead().subtract(roomExpensesBill.getEndReadAmount()));
//            }
//            resultEnergyConsumptionDateList.add(data);
//        }
//        return resultEnergyConsumptionDateList;
//    }
//
//    /**
//     * 获取最新设备消费止码数据
//     * @param list
//     * @return
//     */
//    @Override
//    public Map<String, List<RoomExpensesBill>> getNewestRoomExpensesBillRecordByDeviceCode(List<MeterDeviceConfig> list){
//        try {
//            List<String> deviceCodeList = list.stream().map(MeterDeviceConfig::getDeviceCode).collect(Collectors.toList());
//            List<RoomExpensesBill> roomExpensesBillList = baseMapper.getNewestRoomExpensesBillRecordByDeviceCode(deviceCodeList);
//            if(ObjectUtils.isEmpty(roomExpensesBillList)){
//                return null;
//            }
//            Map<String, List<RoomExpensesBill>> collect = roomExpensesBillList.stream().collect(Collectors.groupingBy(RoomExpensesBill::getDeviceCode));
//            return collect;
//        } catch (Exception ex) {
//            ex.printStackTrace();
//        }
//        return null;
//    }
//
//    @Override
//    public Map<String, List<RoomExpensesBill>> getNewestRoomExpensesBillRecordByDeviceCode(String deviceCode){
//        List<MeterDeviceConfig> list = new ArrayList<>();
//        MeterDeviceConfig meterDeviceConfig = new MeterDeviceConfig();
//        meterDeviceConfig.setDeviceCode(deviceCode);
//        list.add(meterDeviceConfig);
//        return getNewestRoomExpensesBillRecordByDeviceCode(list);
//    }
//
//    /**
//     * 根据时间段获取ES能耗数据
//     * @param settlementTimePeriod  查询时间段
//     * @param list MeterDeviceConfig对象List
//     * @return
//     */
//    @Override
//    public List<EnergyConsumption> getEnergyConsumptionDateList(Date[] settlementTimePeriod, List<MeterDeviceConfig> list){
//        List<EnergyConsumption> energyConsumptionDateList = null;
//        try {
//            EnergyConsumption energyConsumption = new EnergyConsumption();
//            energyConsumption.setQueryPayTimeStart(settlementTimePeriod[0]);
//            energyConsumption.setQueryPayTimeEnd(settlementTimePeriod[1]);
//            Page page = new Page(1,0);
//            energyConsumptionDateList = energyConsumptionService.getEnergyConsumptionDate(page, energyConsumption, list);
//        } catch (Exception e) {
//            log.error("ES查询异常：" + e.getMessage());
//            throw e;
//        }
//        return energyConsumptionDateList;
//    }
//
//    @Override
//    public List<EnergyConsumption> getEnergyConsumptionDateListNew(Date[] settlementTimePeriod, List<MeterDeviceConfig> list){
//        List<EnergyConsumption> energyConsumptionDateList = null;
//        try {
//            EnergyConsumption energyConsumption = new EnergyConsumption();
//            energyConsumption.setQueryPayTimeStart(settlementTimePeriod[0]);
//            energyConsumption.setQueryPayTimeEnd(settlementTimePeriod[1]);
//            Page page = new Page(1,0);
//            energyConsumptionDateList = energyConsumptionService.getEnergyConsumptionDateSupplement(page, energyConsumption, list);
//        } catch (Exception e) {
//            log.error("ES查询异常：" + e.getMessage());
//            throw e;
//        }
//        return energyConsumptionDateList;
//    }
//
//    /**
//     * 批量处理数据，不再区分正常数据和异常数据
//     * @param energyConsumptionDateNormal
//     * @param settlementTimePeriod
//     */
//    public void handlerData(List<EnergyConsumption> energyConsumptionDateNormal, Date[] settlementTimePeriod){
//        for (EnergyConsumption ec:
//                energyConsumptionDateNormal) {
//            calculation(ec, settlementTimePeriod, null, 0);
//        }
//    }
//
//    /**
//     * 读表数据扣费方法(单个处理数据)
//     * @param ec
//     * @param settlementTimePeriod
//     */
//    @Override
//    public void calculation(EnergyConsumption ec, Date[] settlementTimePeriod, String operator, Integer remedyStatus){
//        Integer billingId = baseMeterBillingMapper.getBillingIdByRoomAndMeterType(ec.getRoomId(), ec.getMeterType());
//        if(billingId == null ){
//            return ;
//        }
//        BaseBillingHistory baseBilling = billingStandardService.getNewBaseBillingInfoById(billingId);
//        GlobalRoomInfo globalRoomInfo = roomManagerService.getGlobalRoomInfo(ec.getRoomId());
//
//        //房间余额扣除
//        BigDecimal expensesMoney = baseBilling.getPrice().multiply(ec.getAmount());
//        if(expensesMoney.compareTo(new BigDecimal(0.0)) == 0){
//            log.info("消费为0则不计入计算扣费");
//            return ;
//        }
//        if(ec.getMeterType().equals(0)){
//            deductionBalance(ec.getRoomId(), expensesMoney, null);
//        }else if(ec.getMeterType().equals(1)){
//            deductionBalance(ec.getRoomId(), null, expensesMoney);
//        }else {
//            return ;
//        }
//
//        //保存消费记录
//        RoomExpensesBill roomExpensesBill = new RoomExpensesBill()
//                .setContractId(globalRoomInfo.getRoomTenantryInfo().getId())
//                .setSettlementTimeStart(settlementTimePeriod[0])
//                .setSettlementTimeEnd(settlementTimePeriod[1])
//                .setEnergyAmount(ec.getAmount())
//                .setDeviceCode(ec.getDeviceCode())
//                .setConsumeFee(expensesMoney)
//                .setDeductionStatus(0)
//                .setBillingId(baseBilling.getBillingId())
//                .setRemedyStatus(remedyStatus)
//                .setOperator(operator)
//                .setEndReadAmount(ec.getEndRead())
//                .setVersion(baseBilling.getVersion());
//        saveExpensesBill(roomExpensesBill);
//    }
//
//    /**
//     * 扣费
//     * @param roomId
//     * @param waterBalance
//     * @param electricityBalance
//     * @return
//     */
//    @Override
//    public Object[] deductionBalance(Integer roomId, BigDecimal waterBalance, BigDecimal electricityBalance) {
//        Object[] result = new Object[2];
//        RoomInfo roomInfo = roomInfoMapper.selectById(roomId);
//        if(waterBalance != null){
//            roomInfo.setWaterBalance(roomInfo.getWaterBalance().subtract(waterBalance));
//        }
//
//        if(electricityBalance != null){
//            roomInfo.setElectricityBalance(roomInfo.getElectricityBalance().subtract(electricityBalance));
//        }
//        roomInfoMapper.updateById(roomInfo);
//        meterServiceControl.executeDeviceCommand(roomInfo);
//        result[0] = true;
//        result[1] = "success";
//        return result;
//    }
//
//    /**
//     * 保存消费记录
//     * @param roomExpensesBill
//     */
//    @Override
//    public void saveExpensesBill(RoomExpensesBill roomExpensesBill) {
//        roomExpensesBill.setCreateTime(new Date());
//        roomExpensesBill.setDeductionStatus(0);
//        baseMapper.insert(roomExpensesBill);
//    }
//
//    /**
//     * 获取补录设备数据列表s
//     * @param deviceCode
//     * @param codeGroup 是否按照设备分组
//     * @return
//     */
//    public List<MeterRemedy> getRemedyDeviceList(String deviceCode, Boolean codeGroup){
//        List<MeterRemedy> meterRemedyList = null;
//        if(codeGroup){
//            meterRemedyList = meterRemedyMapper.getNewRemedyDataGroup(deviceCode);
//        }else {
//            meterRemedyList = meterRemedyMapper.getNewRemedyData(deviceCode);
//        }
//        return meterRemedyList;
//    }
//
//    /**
//     * 根据定时任务运行状态获取上次定时任务查询时间段
//     * @return
//     */
//    @Override
//    public Date[] getLastSettlementTimePeriod(){
//        Date[] settlementDate = new Date[2];
//        QueryWrapper qw = new QueryWrapper();
//        qw.orderByDesc("id");
//        List<ExpensesTimerTask> list = expensesTimerTaskMapper.selectList(qw);
//        if(list == null || list.isEmpty()){
//            settlementDate[0] = null;
//            settlementDate[1] = null;
//            return settlementDate;
//        }
//        ExpensesTimerTask expensesTimerTask = list.get(0);
//        settlementDate[0] = expensesTimerTask.getSettlementTimeStart();
//        settlementDate[1] = expensesTimerTask.getSettlementTimeEnd();
//        return settlementDate;
//    }
//
//    /**
//     * 根据定时任务运行状态获取本次定时任务查询时间段
//     * @return
//     */
//    @Override
//    public Date[] getCurrentSettlementTimePeriod() {
//        Date[] settlementDate = new Date[2];
//        QueryWrapper qw = new QueryWrapper();
//        qw.orderByDesc("id");
//        Page page = new Page();
//        page.setCurrent(1);
//        page.setSize(1);
//        IPage<ExpensesTimerTask> expensesTimerTaskPage = expensesTimerTaskMapper.selectPage(page, qw);
//        if(expensesTimerTaskPage == null){
//            settlementDate[0] = null;
//            settlementDate[1] = new Date();
//            return settlementDate;
//        }
//        List<ExpensesTimerTask> list = expensesTimerTaskPage.getRecords();
//
//        if(ObjectUtils.isEmpty(list)){
//            settlementDate[0] = null;
//            settlementDate[1] = new Date();
//            return settlementDate;
//        }
//        ExpensesTimerTask expensesTimerTask = list.get(0);
//        settlementDate[0] = expensesTimerTask.getSettlementTimeEnd();
//        settlementDate[1] = new Date();
//        return settlementDate;
//    }
//
//
//    /**
//     * 保存定时任务运行时间段
//     * @param expensesTimerTask
//     * @param settlementDates
//     */
//    private void saveSettlementTimePeriod(ExpensesTimerTask expensesTimerTask, Date[] settlementDates){
//        expensesTimerTask.setSettlementTimeStart(settlementDates[0]);
//        expensesTimerTask.setSettlementTimeEnd(settlementDates[1]);
//        expensesTimerTaskMapper.insert(expensesTimerTask);
//    }
//
//}
